package com.hdu.dwh.service.impl;

import com.hdu.dwh.dtos.DatawarehouseDatabaseDto;
import com.hdu.dwh.pojos.source_access_pojos.DataWarehouseDatabase;
import com.hdu.dwh.pojos.source_access_pojos.DataWarehouseTable;
import com.hdu.dwh.mapper.DataWarehouseDatabaseMapper;
import com.hdu.dwh.service.IDatabaseAllService;
import com.hdu.dwh.service.ISourceAccessService;
import com.hdu.dwh.utils.OperatorUtil;
import com.hdu.dwh.vos.dataWareHouse_vos.DataWarehouseDatabaseDetailVo;
import com.hdu.dwh.service.DataWarehouseDatabaseService;
import com.hdu.dwh.service.DataWarehouseTableService;
import com.baomidou.mybatisplus.annotation.TableName;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.hdu.dwh.constants.CommonConstants;
import com.hdu.dwh.dao.PaimonBaseDao;
import com.hdu.dwh.enums.HttpStatusEnum;
import com.hdu.dwh.exception.CustomException;
import com.hdu.dwh.exception.DataAlreadyExistException;
import com.hdu.dwh.exception.DataNotFoundException;
import com.hdu.dwh.results.ResponseResult;
import lombok.RequiredArgsConstructor;

import java.util.Set;

import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

/**
 * <p>
 * 源数据库表 服务实现类
 * </p>
 *
 * @author bobo
 * @since 2025-04-08
 */
@Service
@RequiredArgsConstructor
public class DataWarehouseDatabaseServiceImpl extends ServiceImpl<DataWarehouseDatabaseMapper, DataWarehouseDatabase> implements DataWarehouseDatabaseService {

    private final ISourceAccessService sourceAccessService;
    private final IDatabaseAllService databaseAllService;
    @Autowired
    private DataWarehouseTableService datawarehouseTableService;
    private final PaimonBaseDao paimonBaseDao;


    /**
     * 获取源数据库详情 根据id获取单个
     * @param id {@link Long}
     * @return
     */
    @Override
    public ResponseResult getDetailById(Long id) {
        if(id == null){
            return ResponseResult.fail(CommonConstants.PARAM_IS_NULL);
        }
        DataWarehouseDatabase getById = getById(id);
        if(getById == null){
            return ResponseResult.fail(CommonConstants.RECORD_NOT_EXIST);
        }
        return ResponseResult.success(getById);
    }

    @Override
    public DataWarehouseDatabase queryByNameAndSourceAccessIdAndSourceType(String targetDatabase, String sourceType,  Long sourceAccessId) {
        // 查询是否存在
        return lambdaQuery()
            .eq(DataWarehouseDatabase::getDatabaseName, targetDatabase)
            .eq(DataWarehouseDatabase::getSourceType, sourceType)
            .eq(sourceAccessId != null, DataWarehouseDatabase::getSourceAccessId, sourceAccessId)
            .last("LIMIT 1")
            .one();
    }

    /**
     * 根据目标数据库名称删除源数据库
     * @param dbName
     * @throws Exception 
     * 
     */
    @Override
    public void deleteByDatabaseName(String dbName) throws Exception {
        if(this.paimonBaseDao.checkDatabaseExists(dbName) == false) {
            throw new CustomException(HttpStatusEnum.DATABASE_NOT_EXISTS);
        }
        this.paimonBaseDao.deleteDatabase(dbName);
        this.datawarehouseTableService.removeByDatabase(this.getByDatabaseName(dbName));
        this.removeById(this.getByDatabaseName(dbName));
    }

    @Override
    public DataWarehouseDatabase createPaimonDatabase(DatawarehouseDatabaseDto dwhDatabaseDto) throws Exception {
        // 湖仓中添加数据库
        if(this.paimonBaseDao.checkDatabaseExists(dwhDatabaseDto.getDatabaseName()) ) {
            // Get table name from @TableName annotation
            throw new DataAlreadyExistException(DataWarehouseDatabase.class.getAnnotation(TableName.class), CommonConstants.RECORD_EXIST);
        }
        
        this.paimonBaseDao.createDatabase(dwhDatabaseDto.getDatabaseName());
        // 数据库表中添加记录
        DataWarehouseDatabase dwhDatabase = new DataWarehouseDatabase()
            .setDataType(0)
            .setSourceType("paimon")
                .setCreatedBy(OperatorUtil.getCurrentOperator());
        BeanUtils.copyProperties(dwhDatabaseDto, dwhDatabase);
        this.save(dwhDatabase);
        this.getById(dwhDatabase.getId());
        return dwhDatabase;
    }

    @Override
    public DataWarehouseDatabase createSourceDatabase(Long sourceAccessId, String sourceDatabase, String sourceType, Integer dataType) {
        DataWarehouseDatabase dwhdb = new DataWarehouseDatabase()
            .setSourceAccessId(sourceAccessId)
            .setDatabaseName(sourceDatabase)
            .setSourceType(sourceType)
            .setDataType(dataType)
                .setCreatedBy(OperatorUtil.getCurrentOperator());
        this.save(dwhdb);
        return this.getById(dwhdb.getId());
    }

    @Override
    public Set<DataWarehouseDatabaseDetailVo> listDwhDatabaseDetail() {
        return this.baseMapper.getAllDwhDatabaseDetail();
    }

    @Override
    public DataWarehouseDatabase getByDatabaseName(String databaseName) {
        DataWarehouseDatabase dwhdb = this.lambdaQuery()
            .eq(DataWarehouseDatabase::getDatabaseName, databaseName)
            .last("LIMIT 1")
            .one();
        return dwhdb;
    }

    @Override
    public DataWarehouseDatabase updateDatabase(Integer id, DatawarehouseDatabaseDto entity) throws Exception {
        DataWarehouseDatabase dwhdb = this.getById(id);
        if(dwhdb == null) {
            throw new DataNotFoundException(DataWarehouseDatabase.class.getAnnotation(TableName.class), CommonConstants.RECORD_NOT_EXIST);
        }
        // 设置更新用户
        dwhdb.setUpdatedBy(OperatorUtil.getCurrentOperator());
        BeanUtils.copyProperties(entity, dwhdb);
        this.updateById(dwhdb);
        this.paimonBaseDao.alterDatabaseName(dwhdb.getDatabaseName(), entity.getDatabaseName());
        return dwhdb;
    }

    @Override
    public DataWarehouseDatabase getByDwhTable(DataWarehouseTable dwhTable) throws DataNotFoundException {
        DataWarehouseDatabase dwhdb = this.getById(dwhTable.getDatabaseId());
        if(dwhdb == null) {
            throw new DataNotFoundException(DataWarehouseDatabase.class.getAnnotation(TableName.class), CommonConstants.RECORD_NOT_EXIST);
        }
        return dwhdb;
    }
}